const dayjs = require('dayjs');
/**
 * 智能缓存类
 * 支持TTL过期和模式匹配清除
 */
class SmartCache {
  /**
   * 构造函数
   * @param {String} namespace 缓存命名空间
   * @param {Number} ttl 缓存生存时间(毫秒)
   */
  constructor(namespace = 'default', ttl = 300000) {
    this.namespace = namespace;
    this.ttl = ttl;
    this.cache = {};
  }
  
  /**
   * 缓存键前缀
   * @param {String} key 原始键
   * @returns {String} 带命名空间的完整键
   */
  getFullKey(key) {
    return `${this.namespace}:${key}`;
  }
  
  /**
   * 获取缓存，如果不存在则通过fetchFn获取并缓存
   * @param {String} key 缓存键
   * @param {Function} fetchFn 获取数据的函数
   * @returns {Promise<any>} 缓存数据
   */
  async get(key, fetchFn) {
    const fullKey = this.getFullKey(key);
    const now = dayjs().valueOf();
    const cached = this.cache[fullKey];
  
    // 缓存有效
    if (cached && now - cached.timestamp < this.ttl) {
      console.log(`[SmartCache] 命中缓存: ${fullKey}`);
      return cached.data;
    }
  
    // 缓存无效，调用获取函数
    console.log(`[SmartCache] 未命中缓存: ${fullKey}`);
    try {
      const data = await fetchFn();
    
      // 缓存结果
      this.cache[fullKey] = {
        data,
        timestamp: now
      };
    
      return data;
    } catch (err) {
      console.error(`[SmartCache] 获取数据失败: ${fullKey}`, err);
      throw err;
    }
  }
  
  /**
   * 设置缓存
   * @param {String} key 缓存键
   * @param {any} data 缓存数据
   */
  set(key, data) {
    const fullKey = this.getFullKey(key);
    this.cache[fullKey] = {
      data,
      timestamp: dayjs().valueOf()
    };
  }
  
  /**
   * 删除指定键的缓存
   * @param {String} key 缓存键
   */
  remove(key) {
    const fullKey = this.getFullKey(key);
    delete this.cache[fullKey];
  }
  
  /**
   * 使用正则表达式模式匹配删除缓存
   * @param {String} pattern 正则表达式字符串
   */
  removeByPattern(pattern) {
    const regex = new RegExp(pattern);
    const prefix = `${this.namespace}:`;
  
    Object.keys(this.cache).forEach(fullKey => {
      // 移除命名空间前缀再匹配
      const key = fullKey.substring(prefix.length);
      if (regex.test(key)) {
        console.log(`[SmartCache] 模式删除: ${fullKey}`);
        delete this.cache[fullKey];
      }
    });
  }
  
  /**
   * 清空当前命名空间下所有缓存
   */
  clear() {
    const prefix = `${this.namespace}:`;
  
    Object.keys(this.cache).forEach(fullKey => {
      if (fullKey.startsWith(prefix)) {
        delete this.cache[fullKey];
      }
    });
  }
  
  /**
   * 检查缓存是否存在且有效
   * @param {String} key 缓存键
   * @returns {Boolean} 是否有效
   */
  isValid(key) {
    const fullKey = this.getFullKey(key);
    const cached = this.cache[fullKey];
    const now = dayjs().valueOf();
    
    return cached && now - cached.timestamp < this.ttl;
  }
  
  /**
   * 获取缓存键列表
   * @returns {Array<String>} 缓存键列表
   */
  getKeys() {
    const prefix = `${this.namespace}:`;
    return Object.keys(this.cache)
      .filter(key => key.startsWith(prefix))
      .map(key => key.substring(prefix.length));
  }
}

export default SmartCache; 